﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using NUnit.Core;
using NUnit.Core.Extensibility;

namespace JacketEmblem.Crane.UnitTests.NUnitExtensions
{
    [NUnitAddin]
    public class DataFileTestCaseBuilder : IAddin, ITestCaseBuilder
    {
        private static readonly string DataFileAttributeAttributeName = typeof(DataFileAttribute).FullName;

        #region IAddin Members

        public bool Install(IExtensionHost host)
        {
            if (host == null)
            {
                throw new ArgumentNullException("host");
            }

            bool extensionInstalled = false;
            IExtensionPoint testCaseBuilders = host.GetExtensionPoint("TestCaseBuilders");
            if (testCaseBuilders != null)
            {
                testCaseBuilders.Install(this);
                extensionInstalled = true;
            }

            return extensionInstalled;
        }

        #endregion

        #region ITestCaseBuilder Members

        public Test BuildFrom(MethodInfo method)
        {
            TestSuite suite = new TestSuite(method.DeclaringType.Name, method.Name);
            DataFileAttribute testAttribute = Reflect.GetAttribute(method, DataFileAttributeAttributeName, false) as DataFileAttribute;
            if (testAttribute != null)
            {
                Type readerType = testAttribute.ReaderType;
                if (readerType.IsSubclassOf(typeof(DataFileReader)))
                {
                    string dataSource = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, testAttribute.FileName);
                    DataFileReader reader = Activator.CreateInstance(readerType) as DataFileReader;
                    reader.ReadDataFile(dataSource);
                    foreach (DataFileTestInfo info in reader.Tests)
                    {
                        suite.Add(new DataFileTestCase(method, info.Name, info.Arguments));
                    }
                }
            }

            return suite;
        }

        public bool CanBuildFrom(MethodInfo method)
        {
            bool canBuild = false;
            if (method != null)
            {
                canBuild = Reflect.HasAttribute(method, DataFileAttributeAttributeName, false);
            }

            return canBuild;
        }

        #endregion
    }
}
